#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define SOURCE_IP "192.168.56.128"
#define SOURCE_PORT 8888
#define DESTINATION_IP "192.168.56.1"
#define DESTINATION_PORT 12345
unsigned short get_checksum(unsigned short *ptr, int len) {  
    register long sum;  
    unsigned short oddbyte;  
    register short answer;  
    sum = 0;  
    while (len > 1) {  
        sum += *ptr++;  
        len -= 2;  
    }  
    if (len == 1) {  
        oddbyte = 0;  
        *((unsigned char*)&oddbyte) = *(unsigned char*)ptr;  
        sum += oddbyte;  
    }  
    sum = (sum >> 16) + (sum & 0xffff);  
    sum += (sum >> 16);  
    answer = (short)~sum;  
    return answer;  
} 
unsigned short get_tcp_checksum(unsigned short *addr, int len, in_addr_t saddr, in_addr_t daddr) {  
    register long sum = 0;  
    unsigned short answer;  
    unsigned short *w = addr;  
    unsigned short oddbyte;  
    sum += saddr;  
    sum += daddr;  
    sum += htons(IPPROTO_TCP);
    sum += htons(len);
    while(len > 1) {  
        sum += *w++;  
        len -= 2;  
    }   
    if(len == 1) {  
        oddbyte = 0;  
        *((unsigned char*)&oddbyte) = *(unsigned char*)w;  
        sum += oddbyte;  
    }   
    sum = (sum >> 16) + (sum & 0xffff);  
    sum += (sum >> 16);  
    answer = ~sum;   
    return answer;  
}  
int main() {
    int sockfd;
    char buffer[4096]={0};
    char data[5]="hello";
    memset(buffer,0,sizeof(buffer));
    struct iphdr *iph = (struct iphdr *) buffer;
    struct tcphdr *tcph = (struct tcphdr *) (buffer + sizeof(struct iphdr));
    sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    if (sockfd < 0) {
        perror("socket");
        exit(1);
    }
    memset(buffer, 0, sizeof(buffer));
    iph->ihl = 5;
    iph->version = 4;
    iph->tos = 0;
    iph->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr) + sizeof(data);
    iph->id = htonl(54321);
    iph->frag_off = 0;
    iph->ttl = 255;
    iph->protocol = IPPROTO_TCP;
    iph->saddr = inet_addr(SOURCE_IP);
    iph->daddr = inet_addr(DESTINATION_IP);
    iph->check = get_checksum((unsigned short*)buffer,iph->tot_len);
    tcph->source = htons(SOURCE_PORT);
    tcph->dest = htons(DESTINATION_PORT);
    tcph->seq = htonl(0x11111111);
    tcph->ack_seq = htonl(0x22222222);
    tcph->doff = 5; 
    tcph->syn = 1;
    tcph->fin = 1;
    tcph->psh = 1;
    tcph->ack = 1;
    tcph->rst = 1;
    tcph->urg = 1;
    tcph->window = htons(0x1234);
    tcph->urg_ptr = 0;
    memcpy((void*)(buffer + sizeof(struct iphdr) + sizeof(struct tcphdr)), (void*)data, sizeof(data));
    tcph->check = get_tcp_checksum((unsigned short *)tcph,sizeof(struct tcphdr)+sizeof(data),inet_addr(SOURCE_IP),inet_addr(DESTINATION_IP));
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));  
    sin.sin_family = AF_INET;  
    sin.sin_addr.s_addr = inet_addr(DESTINATION_IP);   
    if (sendto(sockfd, buffer, iph->tot_len, 0, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
        perror("sendto");
        exit(1);
    }
    close(sockfd);
    return 0;
}